home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: Taifun
/
Taifun 040 (1987-11-15)(Ossowski, Stefan)(DE)(PD).zip
/
Taifun 040 (1987-11-15)(Ossowski, Stefan)(DE)(PD).adf
/
SimCPM
/
simcpm1.asm
< prev
next >
Wrap
Assembly Source File
|
1989-01-18
|
49KB
|
1,613 lines
vermaj equ $01 ;Major version number
vermin equ $00 ;Minor version number
revyear equ $87 ;Year last assembled
revmonth equ $09 ;Month last assembled
revday equ $15 ;Day last assembled
*************************************************************************
* *
* *
* 8080 Simulator for MC68000 *
* *
* With CP/M 2.2 call support, and optional tracing *
* *
* *
* Converted to AmigaDOS September 1987 by Charlie Gibbs *
* (after painstakingly typing it all in from Dr. Dobbs *
* Journal, January through March 1986). Improvements *
* described by Jim Cathey in his letter in the June 1986 *
* DDJ have been included. Repetitive code is generated *
* by macros whenever it would save my fingers. *
* *
* *
* Version 1.2 1/21/85 JEC *
* Fixed Extent bug in OPEN logic. *
* Sped up code, sample MAC from 2:13 to 1:40 *
* Now runs at a 1.4 MHz equivalent based on MAC sample. *
* *
* Version 1.1 8/29/84 JEC *
* Fixed BIOS call #6 bug. *
* *
* Version 1.0 05/25/84 by Jim Cathey *
* *
* This program has been written for speed whenever possible, *
* as such tends to be large because of the separate subroutine *
* for each and every opcode of the target processor. *
* *
* On an 8MHz 68000 (Compupro) system the simulation speed is *
* a little better than a 1MHz Z-80 when running MAC. The time *
* for a sample assembly was 2:13 for the simulation vs. 0:35 *
* on a 4MHz Z-80, both systems used identical hard disk systems. *
* *
* It is not a complete simulation, as some flag handling *
* isn't quite right, but it is enough to run the program *
* I wrote for it (DDT, LU, MAC, and Morrow's FORMATW). *
* *
*************************************************************************
code
page
*************************************************************************
* *
* This file contains the startup routines, the simulator core, *
* tracing code, and the CP/M 2.2 simulation. *
* *
*************************************************************************
xref optabl,flags,mloop,traceit,tracesad,traceead,traceflg
xdef illegl,service,dump
h19 equ 1 ;Non-zero for H19 emulation
*
* ASCII character values
*
bel equ $07 ;Bell (or beep or whatever)
bs equ $08 ;Backspace
ht equ $09 ;Horizontal tab
lf equ $0A ;Line feed
ff equ $0C ;Form feed
cr equ $0D ;Carriage return
so equ $0E ;Shift out
si equ $0F ;Shift in
esc equ $1B ;Escape
*
* Register definitions for the simulation
* Note, only leaves D0-D1/A0 free for use by entire
* program without saving registers for temporary use.
*
return equr A6 ;JMP (return) is fast return to MLOOP.
pseudopc equr A5 ;8080's PC is register A5.
opptr equr A4 ;Pointer to opcode dispatch table
pseudosp equr A3 ;8080's SP is register A3.
flagptr equr A2 ;Pointer to 8080's flag lookup table is A2.
targbase equr A1 ;Pointer to 8080's address space is A1.
regs equr A1 ;Base pointer to 8080's registers is A1.
regcon0e equr D7 ;Register-based constant #$E (for speed)
regcon01 equr D6 ;Register-based constant #$1
regcon0f equr D5 ;Register-based constant #$F
regconff equr D4 ;Register-based constant #$FF
regf equr D3 ;8080's flags
rega equr D2 ;8080's accumulator
*
* Target processor's data registers (offsets into storage area)
*
regop3 equ -9 ;Operand 3 for DAA storage
regb equ -8 ;Offsets from register base pointer for
regc equ -7 ; 8080's pseudo-registers.
regd equ -6 ; A and F are in 68000's data registers.
rege equ -5 ; Pseudo-PC is kept in an address register.
regh equ -4
regl equ -3
regop1 equ -2 ;Operand 1 for DAA storage
regop2 equ -1 ; " 2 " " "
page
*--------------------------------
*
* Some commonly used macros
*
*--------------------------------
sys MACRO ;Call a system routine.
jsr _LVO\1(a6)
ENDM
*----------------------
* Equates
*----------------------
Absbase equ 4
MODE_OLDFILE equ 1005
MODE_NEWFILE equ 1006
*----------------------
* External references
*----------------------
XREF _LVOOpenLibrary
XREF _LVOCloseLibrary
XREF _LVOClose
XREF _LVODeleteFile
XREF _LVOInput
XREF _LVOIoErr
XREF _LVOOpen
XREF _LVOOutput
XREF _LVORead
XREF _LVORename
XREF _LVOSeek
XREF _LVOWaitForChar
XREF _LVOWrite
page
*************************************************************************
* *
* Initialization *
* *
*************************************************************************
start: move.l sp,savesp ;Save the stack pointer.
move.b #1,testdol ;"pstring" should test for leading $.
clr.w esclen ;No partial escape sequence is saved.
clr.b insflag ;We're not in insert mode.
clr.b btrcflg ;Turn off BIOS/BDOS call tracing.
clr.b quitflg ;Clear the quit flag.
clr.b bufflag ;Disable output buffering.
clr.b listopn ;The list device is closed.
move.l #strbuf,strptr ;Initialize output buffer pointer.
lea handles,a1
moveq #(handlen-handles)/4-1,d1
clrhand clr.l (a1)+ ;Clear file handles.
dbra d1,clrhand
clr.l rawhand ;Clear RAW: handle too.
*
* Copy the command line to "cmdline", stripping out leading switches if any.
*
lea cmdline,a1
subq #1,d0
* Skip over leading blanks, if any.
leadblk cmpi.b #' ',(a0)+ ;Leading blank?
bne.s bufparm ;No.
dbra d0,leadblk ;Skip over leading blank.
* If the first parameter is "-b", skip over it but activate output buffering.
bufparm subq.l #1,a0 ;Back onto the first non-blank.
cmpi.b #'-',(a0) ;Possible buffer switch?
bne.s savecmd ;No - start saving the command line.
cmpi.b #'B',1(a0) ;Activate output buffering?
beq.s setbuff ;Yes.
cmpi.b #'b',1(a0)
bne.s skipsw ;No.
setbuff move.b #1,bufflag ;Set buffered-output flag.
skipsw cmpi.b #' ',(a0)+ ;Skip over the switch.
beq.s skipswx ; and look for start of command line.
dbra d0,skipsw
addq.l #1,a1 ;Adjust A1.
bra.s gotcmd ;There is no command line left.
skipswx subq.l #1,a0 ;Back onto the first blank.
bra.s leadblk ;Look for the next non-blank.
* Save the command line (except for leading switches).
savecmd move.b (a0)+,(a1)+ ;Save the command line, if any.
dbra d0,savecmd
gotcmd move.b #0,-1(a1) ;Replace the newline with a null.
move.b cmdline,cmdflag ;Save command-line flag.
*
* Open libraries and set up a RAW: window.
*
move.b #1,quitflg ;Quit immediately if failure below.
move.l Absbase,a6 ;Find library
lea dosname,a1 ;'dos.library'
moveq #0,d0 ;Any version
sys OpenLibrary ;Open dos.library.
move.l d0,a6 ;Point to doslib for next operation.
move.l d0,dosbase ;Save it for future reference.
sys Input ;Get file handle for keyboard.
move.l d0,stdin ;Save it here.
beq quitprg ;Couldn't get keyboard handle.
sys Output ;Get file handle for screen.
move.l d0,stdout ;Save it here.
beq quitprg ;Couldn't get screen handle.
move.l #rawspec,d1
move.l #MODE_NEWFILE,d2
sys Open ;Open a RAW: window.
move.l d0,rawhand ;Save the file handle here.
bne.s opened ;We succeeded.
move.l #rawerr,d1
bsr pstring ;Display error message...
sys IoErr
move.l d0,d1
bsr plong ; and error code.
bsr pcrlf
bra quitprg
opened move.b cmdflag,quitflg ;If we have a command, execute it and quit.
move.l #setwin,d1
bsr pstring ;Set the window to 24 by 80.
*
* Come back here to load another program.
*
nextprg lea target,targbase ;Start of target memory
clr.b insflag ;Reset insert mode.
move.l #simsg,d1
bsr pstring ;In case last program sent SHIFT OUT
clr.b dumpcnt ;Reset dump pause counter.
bsr entrads ;Enter trace delimiting addresses.
bsr lodfdos ;Load up the fake FDOS in target memory.
bsr lodregs ;Load the remaining simulation registers.
bsr loadcom ;Load the .COM program.
jmp mloop ;Execute simulation.
page
*************************************************************************
* *
* Illegal instructions and dumping *
* *
*************************************************************************
illegl move.l #illgmsg,d1 ;Illegal opcode, say what & where,
bsr pstring
lea -1(pseudopc),a0
move.b (a0),d1
suba.l targbase,a0
bsr pbyte
move.l #ilgmsg2,d1
bsr pstring
move.l a0,d1
bsr pword
move.l #ilgmsg3,d1
bsr pstring
move.l #dumpmsg,d1
bsr pstring
clr.b dumpcnt
bsr dump ; and spill guts.
bra quitprg ;Quit simulation.
dump movem.l d0-d2,-(sp)
move.l #dmpmsg2,d1 ;Dump all registers,
bsr pstring ; used for illegals and tracing.
lea workbuf,a0
move.b rega,d1 ;Accumulator
bsr ubyte
move.b regf,d1 ;Flags
bsr ubyte
move.b #' ',(a0)+
move.w regb(regs),d1 ;BC
bsr uword
move.b #' ',(a0)+
move.w regd(regs),d1 ;DE
bsr uword
move.b #' ',(a0)+
move.w regh(regs),d1 ;HL
bsr uword
move.b #' ',(a0)+
move.l pseudosp,d1 ;SP
sub.l targbase,d1
bsr uword
move.b #' ',(a0)+
move.l a1,-(sp)
move.l pseudosp,a1
swap d2
move.w #3,d2
tosloop move.b 1(a1),d1 ;Display the top 4 stack entries.
ror.w #8,d1
move.b 0(a1),d1
bsr uword
move.b #' ',(a0)+
addq.l #2,a1
dbra d2,tosloop
move.l (sp)+,a1
swap d2
move.l pseudopc,d1 ;PC
sub.l targbase,d1
bsr uword
move.b #' ',(a0)+
move.b #' ',(a0)+
move.b (pseudopc),d1 ;Current opcode byte
bsr ubyte
move.b #' ',(a0)+
move.b #' ',(a0)+
move.b #'$',(a0)+
move.l #workbuf,d1
bsr pstring ;Displaying as a single string is much faster.
moveq #0,d0
move.b (pseudopc),d0 ;Opcode
mulu #9,d0 ;Offset into opcode table
lea mnops,a0
move.l a0,d1
add.l d0,d1 ;D1 -> opcode name
move.l d1,-(sp)
addq.l #1,d1
bsr pstring ;Display opcode name.
move.l (sp)+,a0
cmpi.b #' ',(a0)
beq.s nooprnd ;There are no operands.
cmpi.b #'C',(a0)
bne.s notcons
move.b 1(pseudopc),d1 ;Display single-byte operand.
bsr pbyte
bra.s nooprnd
notcons cmpi.b #'A',(a0)
bne.s nooprnd
move.b 2(pseudopc),d1 ;Display two-byte operand.
bsr pbyte
move.b 1(pseudopc),d1
bsr pbyte
nooprnd bsr pcrlf
addq.b #1,dumpcnt ;Count the number of times dumped.
cmpi.b #8,dumpcnt ;Is the screen full of dumps?
bmi.s dumpx ;No - exit.
move.l #dmpmsg3,d1
bsr pstring ;Ask for operator action.
bsr dmpstr ;Make sure the prompt gets out!
movem.l d3/a0-a1/a6,-(sp)
move.l rawhand,d1 ;Console input
move.l #dumpcnt,d2
move.l dosbase,a6
moveq #1,d3
sys Read ;Get the operator's reply.
movem.l (sp)+,d3/a0-a1/a6
bsr pcrlf
cmpi.b #'Q',dumpcnt ;Does he want to quit?
beq quitprg ;Yes.
cmpi.b #'q',dumpcnt
beq quitprg
cmpi.b #'G',dumpcnt ;Go on with tracing disabled?
beq.s dumpnt ;Yes.
cmpi.b #'g',dumpcnt
bne.s dmpcont
dumpnt clr.b traceflg ;Disable tracing and continue.
dmpcont clr.b dumpcnt ;Reset the counter.
dumpx movem.l (sp)+,d0-d2
rts
page
*************************************************************************
* *
* Initialization subroutines *
* *
*************************************************************************
*
* Load up the fake FDOS.
*
lodfdos move.l a6,-(sp)
lea fdos,a6
move.l targbase,pseudosp
adda.l #$10000,pseudosp
lea -256(pseudosp),a0
move.w #fdoslen,d0
lodloop move.b (a6)+,(a0)+
dbra d0,lodloop
lea -256(pseudosp),a0
move.l a0,d0
sub.l targbase,d0
move.b #$C3,0(targbase) ;Build BIOS and BDOS jumps.
move.b #$C3,5(targbase)
move.b d0,6(targbase)
rol.w #8,d0
move.b d0,7(targbase)
rol.w #8,d0
addq.w #3,d0
move.b d0,1(targbase)
rol.w #8,d0
move.b d0,2(targbase)
clr.w -(pseudosp) ;Set up a return stack to exit simulation.
move.l (sp)+,a6
rts
*
* Set up working registers.
*
lodregs lea optabl,opptr ;Point base reg. to opcode dispatch table.
lea mloop,return
lea flags,flagptr
move.l targbase,pseudopc
adda.l #$100,pseudopc ;Start execution at 0100H in target space.
moveq #$E,regcon0e ;Set up quick constants.
moveq #$1,regcon01
moveq #$F,regcon0f
move.l #$FF,regconff
moveq #0,rega
moveq #0,regf
rts
page
*
* Get start and end addresses for tracing.
*
entrads tst.b traceit ;Is tracing required?
beq entradx ;No.
move.l #tracemsg,d1 ;Enter trace address if necessary.
bsr pstring
lea workbuf,a0
move.b #workbufn-workbuf-2,(a0)
bsr getline ;Get the string.
moveq #0,d0
move.b 1(a0),d0 ;Number of bytes read
addq.l #2,a0 ;Skip over length information.
clr.b 0(a0,d0) ;Insert string terminator.
bsr atol ;Get trace start address.
and.l #$FFFF,d1
add.l targbase,d1
move.l d1,tracesad
* Now get the ending address.
move.l #tracemg2,d1
bsr pstring
lea workbuf,a0
move.b #workbufn-workbuf-2,(a0)
bsr getline
moveq #0,d0
move.b 1(a0),d0
addq.l #2,a0
clr.b 0(a0,d0)
bsr atol
and.l #$FFFF,d1
add.l targbase,d1
move.l d1,traceead
bsr pcrlf
* Find out whether BIOS/BDOS calls are to be traced.
move.l #btrcmsg,d1
bsr pstring
lea workbuf,a0
move.b #10,(a0)
bsr getline
move.b #1,btrcflg
cmpi.b #'Y',workbuf+2
beq.s entradx
cmpi.b #'y',workbuf+2
beq.s entradx
clr.b btrcflg
entradx clr.b traceflg ;Start with tracing turned off.
rts
*
* Open the file to be loaded, and load it into
* target space if successful.
*
loadcom movem.l d1-d3/a1-a2/a6,-(sp) ;Save registers.
lea cmdline,a0
tst.b cmdflag ;Do we have a command already?
bne.s scancmd ;Yes - process it.
prompt move.l #aprompt,d1
bsr pstring ;Display the command prompt.
lea cmdline,a0
move.b #cmdlinen-cmdline-2,(a0)
bsr getline ;Get a command line.
moveq #0,d0
move.b 1(a0),d0 ;Length of command line
beq.s prompt ;Zero - try again.
addq.l #2,a0 ;Skip over length information.
clr.b 0(a0,d0) ;Insert command line terminator.
cmpi.b #3,(a0) ;Control-C?
bne.s scancmd ;No.
move.b #1,quitflg ;Set quit flag.
bra quitprg ;Exit the simulator.
scancmd lea comname,a2
moveq #comnamen-comname-6,d1 ;Adjust length for DBcc.
loadnam bsr ucase ;Convert file name to upper case.
move.b d0,(a2)+
cmpi.b #' ',(a0) ;End of name?
beq gotname ;Yes.
tst.b (a0) ;End of command string?
dbeq d1,loadnam ;No - keep on going.
gotname move.l a0,comend ;Save position in command line.
move.b #'.',(a2)+ ;Mash file name to .COM.
move.b #'C',(a2)+
move.b #'O',(a2)+
move.b #'M',(a2)+
clr.b (a2)
clr.b cmdline ;Ask for a new command next time.
move.l #comname,d1
move.l #MODE_OLDFILE,d2
move.l dosbase,a6
sys Open ;Open the file.
tst.l d0 ;Did the open fail?
bne.s comopen ;No.
lea comname,a0
openerr cmpi.b #'.',(a0)+ ;Find end of file name.
bne.s openerr
move.b #'?',-1(a0)
move.b #cr,(a0)+
move.b #lf,(a0)+
move.b #'$',(a0)
move.l #comname,d1
bsr pstring ;Echo "name?"
bra prompt ;Try again.
comopen move.l d0,-(sp) ;Save the file handle.
move.l d0,d1
move.l pseudopc,d2 ;Start loading at $0100 in target.
move.l #65536-512,d3 ;Maximum number of bytes to load
move.l dosbase,a6
sys Read ;Load the .COM file.
move.l (sp)+,d1
move.l dosbase,a6
sys Close ;Close the .COM file.
* The program has now been loaded.
movem.l (sp)+,d1-d3/a1-a2/a6 ;Refresh registers.
movem.l d1-d3/a1-a2/a6,-(sp)
lea $80(targbase),a0 ;Set up target's base page.
move.l a0,dmaaddr
* Set up FCBs and command line tail.
lea $5C(targbase),a0
lea $6C(targbase),a2
clr.b (a0)+
clr.b (a2)+
moveq #10,d0
clrfcb move.b #' ',(a0)+ ;Clear FCBs.
move.b #' ',(a2)+
dbra d0,clrfcb
clr.b $80(targbase) ;Clear the command line tail.
move.l comend,a0 ;Restore position in command line.
fcb1 tst.b (a0) ;End of command line?
beq loaded ;Yes.
cmpi.b #' ',(a0)+ ;Skip over to first file name
beq.s fcb1
subq.l #1,a0 ;Back onto start of file name.
move.l a0,-(sp) ;Save position on command line.
lea $81(targbase),a2;A2 loads the command line tail.
gettail move.b (a0)+,(a2)+ ;Copy the command tail.
bne.s gettail
move.l a2,d0
lea $82(targbase),a0;Don't count null terminator!
sub.l a0,d0
move.b d0,$80(targbase);Length of command line tail
move.l (sp)+,a0 ;Go back to the first file name.
lea $5C(targbase),a2;Address of current FCB
getfcb move.l a2,fcbptr ;Save pointer to current FCB.
cmpi.b #':',1(a0) ;Is a drive specified?
bne.s getfcbf ;No.
move.b (a0),(a2) ;Get drive letter.
subi.b #'A'-1,(a2) ;Convert to drive code.
addq.l #2,a0 ;Skip over drive designator.
tst.b (a0) ;End of command line?
beq.s loaded ;Yes - we're done.
cmpi.b #' ',(a0) ;End of file name?
beq.s getfcbx ;Yes.
getfcbf addq.l #1,a2 ;Start of file name in FCB
getfcbl move.b (a0)+,(a2)+ ;Copy file name to FCB.
getfcbt tst.b (a0) ;End of command?
beq.s loaded ;Yes.
cmpi.b #' ',(a0) ;End of file name?
beq.s getfcbx ;Yes.
cmpi.b #'.',(a0) ;Start of file name extension?
bne.s getfcbl ;No - continue loading file name.
move.l fcbptr,a2 ;Copy original pointer
adda.l #9,a2 ;Skip over to extension field.
addq.l #1,a0 ;Skip over the period.
bra.s getfcbt
getfcbx tst.b (a0) ;End of command line?
beq.s loaded ;Yes.
cmpi.b #' ',(a0)+ ;Look for another file name.
beq.s getfcbx
subq.l #1,a0 ;Back onto start of file name.
move.l fcbptr,d0
lea $5C(targbase),a2
cmp.l d0,a2 ;Was this the first FCB?
bne.s loaded ;No - stop after two FCBs.
adda.l #16,a2 ;Skip over to the next FCB.
bra.s getfcb ;Load the next FCB.
loaded movem.l (sp)+,d1-d3/a1-a2/a6 ;Restore registers.
rts ;Exit.
*
* Subroutine to get a character and convert it to upper case
*
ucase move.b (a0)+,d0
cmpi.b #'a',d0
blt.s ucasex
cmpi.b #'z',d0
bgt.s ucasex
subi.b #'a'-'A',d0
ucasex rts
page
*************************************************************************
* *
* BDOS / BIOS service routines *
* *
*************************************************************************
service movem.l a1/a6,-(sp)
move.b rega,newrega ;Save 8080 accumulator (D2)
move.l dosbase,a6 ;Get dos.library pointer
* Decode the byte following the HLT instruction (BIOS call type).
moveq #0,d0 ;Handle BIOS/BDOS service request
move.b (pseudopc)+,d0 ; of form HLT DB opcode.
cmp #(biostabn-biostab)/4,d0
blt.s dobios ;Function number is within range.
badbios move.b d0,-(sp) ;Flag illegal BIOS call
move.l #ilgbios,d1 ; and spill guts.
bsr pstring
move.b (sp)+,d1
bsr pbyte
bsr pcrlf
bsr dump
bra quitprg
dobios move.l d0,-(sp) ;Save BIOS function number.
beq.s biostrx ;Zero - it's a BDOS call.
tst.b btrcflg ;Trace BIOS calls?
beq.s biostrx ;No.
move.l #biosmsg,d1
bsr pstring
move.l (sp),d1
bsr pbyte
move.l #atmsg,d1
bsr pstring
move.b 1(pseudosp),d1 ;Address where called (top stack entry)
ror.w #8,d1
move.b 0(pseudosp),d1
bsr pword
bsr pcrlf
move.l (sp),d0
biostrx asl #2,d0 ;Multiply function number by 4.
addi.l #biostab,d0 ;Point at address table entry.
movea.l d0,a0
movea.l (a0),a0 ;Point to appropriate service routine.
move.l (sp)+,d0 ;Restore BIOS function number.
jmp (a0) ;Jump to the routine.
* If the BIOS code is zero, it's a BDOS call.
* Decode register C using a similar routine to the BIOS decoding above.
bdosfn moveq #0,d0
move.b regc(regs),d0 ;Get BDOS function number.
cmp #(bdostabn-bdostab)/4,d0
blt.s dobdos ;Function number is within range.
badbdos move.b d0,-(sp)
move.l #ilgbdos,d1 ;Illegal or unsupported BDOS call
bsr pstring
move.b (sp)+,d1
bsr pbyte
bsr pcrlf
bsr dump
bra quitprg
dobdos move.l d0,-(sp) ;Save BDOS function number.
tst.b btrcflg ;Trace BDOS calls?
beq.s bdostrx ;No.
move.l #bdosmsg,d1
bsr pstring
move.l (sp),d1
bsr pbyte
move.l #atmsg,d1
bsr pstring
move.b 1(pseudosp),d1
ror.w #8,d1
move.b 0(pseudosp),d1
bsr pword
bsr pcrlf
move.l (sp),d0
bdostrx cmpi.b #10,d0 ;BDOS function 10 or higher?
blt.s bdosjmp ;No.
bsr dmpstr ;Dump any outstanding console output.
move.l (sp),d0 ;Restore BDOS function number.
bdosjmp asl #2,d0 ;Multiply function number by 4.
addi.l #bdostab,d0 ;Point at address table entry.
movea.l d0,a0
movea.l (a0),a0 ;Point to appropriate service routine.
move.l (sp)+,d0 ;Restore BDOS function number.
moveq #0,d1
move.w regd(regs),d1 ;Get argument.
jmp (a0) ;Jump to the routine.
* Return here after performing the BDOS function.
results movem.l (sp)+,a1/a6
moveq #0,rega
move.b newrega,rega ;Get new accumulator value.
* We have finished processing the BDOS function.
move.b rega,d0 ;Set flags.
and.w regconff,d0
move.b 0(flagptr,d0.w),regf
rts
*
* Individual BDOS service routines
*
bdos00 bra quitprg ;Exit program.
bdos01 bsr dmpstr ;Console input
move.l rawhand,d1
move.l #newrega,d2
moveq #1,d3
sys Read
bra results
bdos02 move.b rege(regs),d1 ;Console output
clr.b testdol ;Allow dollar signs
bsr pchar
bra results
bdos03 equ badbdos ;Reader input
bdos04 equ badbdos ;Punch output
bdos05 pea rege(regs) ;List output byte
bdos05t tst.b listopn ;Is the printer already open?
bne.s bdos05w ;Yes.
move.l #prtname,d1
move.l #MODE_NEWFILE,d2
sys Open ;Open the printer.
move.l d0,prthand ;Save the file handle.
bne.s bdos05o ;The open was successful.
move.l #badprt,d1
bsr pstring ;Indicate an unsuccessful open.
bsr dump ;Spill guts...
bra quitprg ; and exit.
bdos05o move.b #1,listopn ;Indicate that the list device is open.
bdos05w move.l prthand,d1
move.l (sp)+,d2 ;Character to send to the list device
moveq #1,d3 ;Just send one byte.
sys Write ;Send the byte to the list device.
bra results
bdos06 cmpi.b #$FF,rege(regs) ;Direct console I/O
bne.s bdos02 ;Send the byte.
bsr dmpstr ;Dump any outstanding output.
move.l rawhand,d1
moveq #1,d2 ;Wait for one microsecond.
sys WaitForChar ;Check whether a character is ready.
tst.l d0 ;Is a character ready?
bne bdos01 ;Yes - get it.
clr.b newrega ;Indicate that nothing is ready.
bra results
bdos07 move.b 3(targbase),newrega ;Get IOBYTE
bra results
bdos08 move.b rege(regs),3(targbase) ;Set IOBYTE
bra results
bdos09 add.l targbase,d1 ;Console output string
bsr pstring
bra results
bdos10 add.l targbase,d1 ;Console input line
movea.l d1,a0 ;The buffer is here.
bsr getline ;Get a line.
cmpi.b #3,2(a0) ;Was it a control-C?
bne results ;No - continue processing.
bra quitprg ;Terminate the program.
bdos11 move.l rawhand,d1 ;Console status check
moveq #1,d2 ;Wait for one microsecond.
sys WaitForChar ;Check whether a character is ready.
move.b d0,newrega ;Result is compatible with CP/M.
bra results
bdos12 clr.b regh(regs) ;Get system identification
move.b #$22,regl(regs) ;Pretend we're CP/M 2.2.
bra results
bdos13 equ results ;Reset all drives (ignored)
bdos14 move.b rege(regs),4(targbase) ;Select drive
bra results
bdos15 move.l #MODE_OLDFILE,d2;Open existing file
bdos15o add.l targbase,d1
movea.l d1,a0 ;The FCB is here.
move.l d1,-(sp)
lea opnname,a1 ;Build AmigaDOS file name here.
move.l a1,d1 ;We'll need it here.
bsr convfn ;Make a file name.
sys Open ;Open the file.
move.l (sp)+,a1 ;The FCB is here.
lea handles,a0
moveq #(handlen-handles)/4-1,d1
clr.b newrega ;Assume the open succeeded.
tst.l d0 ;Did it fail?
bne bdos15s ;No.
move.b #$FF,newrega ;Set failure code.
bra results
bdos15s tst.l (a0)+ ;Find an available handle slot.
dbeq d1,bdos15s
tst d1 ;Did we find a slot?
bmi bdos15e ;No - error!
move.l d0,-4(a0) ;Save file handle address.
moveq #(handlen-handles)/4-1,d0
sub.l d1,d0
move.b d0,13(a1) ;Save handle number in FCB.
bra results
bdos15e move.l #fullmsg,d1 ;File handle table overflow!
bsr pstring ;Display an error message
bra quitprg ; and forget the whole thing.
bdos16 move.b #$FF,newrega ;Close file
bsr gethand ;Get the file handle.
beq results ;The file is not open.
clr.l 0(a1,d0.w) ;Clear the handle table entry.
sys Close ;Close the file.
clr.b newrega ;Indicate success.
bra results
bdos17 equ badbdos ;Search for first file
bdos18 equ badbdos ;Search for next file
bdos19 add.l targbase,d1 ;Delete file
movea.l d1,a0 ;The FCB is here.
lea opnname,a1 ;Build AmigaDOS file name here.
move.l a1,d1 ;We'll need it here.
bsr convfn ;Make a file name.
sys DeleteFile ;Delete the file.
bra results
bdos20 clr.b newrega ;Sequential read
bsr gethand
move.l dmaaddr,d2
move.l #128,d3
sys Read
tst.l d0 ;Were we successful?
bgt results ;Yes.
move.b #$FF,newrega ;Set failure (EOF) flag.
bra results
bdos21 clr.b newrega ;Sequential write
bsr gethand
move.l dmaaddr,d2
move.l #128,d3
sys Write
tst.l d0 ;Were we successful?
bgt results ;Yes.
move.b #$FF,newrega ;Set failure flag.
bra results
bdos22 move.l #MODE_NEWFILE,d2 ;Make new file
bra bdos15o ;Use BDOS 15 open routine
bdos23 add.l targbase,d1 ;Rename file
movea.l d1,a0
lea opnname,a1
bsr convfn ;Convert old file name.
movea.l d1,a0
adda.l #16,a0
lea renname,a1
bsr convfn ;Convert new file name.
move.l #opnname,d1
move.l #renname,d2
sys Rename ;Rename the file.
bra results
bdos24 equ badbdos ;Get active drive map
bdos25 move.b 4(targbase),newrega ;Get default drive number
bra results
bdos26 add.l targbase,d1 ;Set file buffer address
move.l d1,dmaaddr
bra results
bdos27 equ badbdos ;Get allocation vector
bdos28 equ badbdos ;Protect drive
bdos29 equ badbdos ;Get read-only map
bdos30 equ badbdos ;Set file attributes
bdos31 equ badbdos ;Get disk parameter block
bdos32 equ badbdos ;Get or set user code
bdos33 pea _LVORead(a6) ;Direct access read
bra.s bdos34c ;Use common read/write routine.
bdos34 pea _LVOWrite(a6) ;Direct access write
bdos34c clr.b newrega ;Common direct access read/write routine
bsr gethand
move.l d1,-(sp) ;Save file handle.
moveq #0,d2
move.b 35(a0),d2 ;Get seek address.
rol.l #8,d2
move.b 34(a0),d2
rol.l #8,d2
move.b 33(a0),d2
rol.l #7,d2 ;Convert record number to byte displacement.
move.b 33(a0),32(a0) ;Set up current record number in extent.
andi.b #$7F,32(a0)
moveq #14,d0
ror.l d0,d2
move.b d2,12(a0) ;Current extent number
rol.l d0,d2
moveq #-1,d3
sys Seek ;Seek to desired position.
move.l (sp)+,d1 ;Get the file handle again.
move.l (sp)+,a0 ;Address of read or write routine
tst.l d0 ;Were we successful?
bmi bdos34e ;No.
move.l dmaaddr,d2
move.l #128,d3
jsr (a0) ;Read or write the desired record.
tst.l d0 ;Were we successful?
bgt results ;Yes.
bdos34e move.b #6,newrega ;Set failure (invalid address) flag.
bra results
bdos35 equ badbdos ;Get file end address
bdos36 equ badbdos ;Get direct address
*
* Individual BIOS service routines
*
bios01 bra quitprg ;Warm boot
bios02 equ bdos11 ;Console status check
bios03 equ bdos01 ;Console input byte
bios04 move.b regc(regs),d1 ;Console output byte
clr.b testdol ;Allow dollar signs
bsr pchar
bra results
bios05 pea regc(regs) ;List output byte
bra bdos05t
bios06 equ badbios ;Punch output byte
bios07 equ badbios ;Reader input byte
bios08 equ badbios ;Home disk
bios09 equ badbios ;Select disk
bios10 equ badbios ;Set track
bios11 equ badbios ;Set sector
bios12 equ badbios ;Set DMA address
bios13 equ badbios ;Read disk
bios14 equ badbios ;Write disk
bios15 move.b #$FF,newrega ;List status
bra results
*
* End of program, one way or another
*
quitprg move.l savesp,sp ;Restore stack pointer.
bsr dmpstr ;Dump any outstanding console output.
* If the list device was used, close it.
tst.b listopn ;Is the printer open?
beq.s closprt ;No.
move.l prthand,d1
sys Close ;Close the printer.
closprt clr.b listopn ;Reset the "printer-open" flag.
* If any files were left open by the last program, close them.
lea handles,a0
moveq #(handlen-handles)/4-1,d0
closall move.l (a0)+,d1
beq.s closnxt ;This file isn't open.
movem.l a0/d0,-(sp)
move.l dosbase,a6
sys Close ;Close this file.
movem.l (sp)+,a0/d0
closnxt dbra d0,closall
* Check whether we should quit the simulation.
tst.b quitflg ;Exit the simulator?
bne.s exitsim ;Yes.
tst.b cmdflag ;Was .COM file loaded from command line?
beq nextprg ;No - re-display the command prompt.
* Terminate execution of the simulator.
exitsim move.l rawhand,d1 ;Is RAW: open?
beq.s closlib ;No.
move.l dosbase,a6
sys Close ;Close RAW:
closlib move.l Absbase,a6
move.l dosbase,a1
sys CloseLibrary ;Close dos.library.
moveq #0,d0 ;Return with no error.
rts ;All done
page
*************************************************************************
* *
* AmigaDOS interface routines *
* *
*************************************************************************
*
* Get a line from the console. CP/M BDOS 10 conventions are used.
* A0 is assumed to point to the start of the buffer.
* If the first character encountered is a control-C, this routine
* exits, leaving just the control-C in the buffer.
*
getline movem.l d2-d3/a0-a1/a6,-(sp)
bsr dmpstr ;Flush the screen buffer first.
move.l dosbase,a6
movea.l a0,a1
addq.l #2,a1 ;The current character loads here.
clr.b 1(a0) ;Clear character count.
getlinl move.l rawhand,d1 ;Read from RAW:
move.l a1,d2 ; into current position
moveq #1,d3 ; for a length of one byte.
movem.l d1-d3/a0-a1,-(sp)
sys Read ;Get a character.
movem.l (sp)+,d1-d3/a0-a1
cmpi.b #cr,(a1) ;Did we get a carriage return?
beq.s getlinc ;Yes - stop here.
cmpi.b #lf,(a1) ;Stop on a line feed too.
beq.s getlinc
cmpi.b #bs,(a1) ;Backspace?
bne.s getlinp ;No.
tst.b 1(a0) ;Do we have anything yet?
beq.s getlinl ;No - ignore the backspace.
subq.l #1,a1 ;Back over the previous character.
subq.b #1,1(a0) ;Decrement character count.
movem.l a0-a1,-(sp)
move.l #bsmsg,d1
jsr pstring ;Erase the previous character on the screen.
movem.l (sp)+,a0-a1
bra.s getlinl
getlinp movem.l a0-a1,-(sp)
sys Write ;Echo the current character.
movem.l (sp)+,a0-a1
getlinn addq.b #1,1(a0) ;Bump character count.
move.b 1(a0),d0 ;Number of bytes read so far.
cmpi.b #3,(a1)+ ;Did we get a control-C?
bne.s getlinf ;No.
cmpi.b #1,d0 ;Is is the first character?
beq.s getlinx ;Yes - exit now.
getlinf cmp.b (a0),d0 ;Is the buffer full?
bne.s getlinl ;No - try for another character.
bra.s getlinx
getlinc bsr pcrlf ;Carriage return or line feed
getlinx movem.l (sp)+,d2-d3/a0-a1/a6
rts ;Exit.
*
* Display the message pointed to by D1.
* The message must be terminated by a dollar sign.
*
pstring movem.l d2-d3/a1-a2,-(sp) ;Save work registers.
move.l d1,a0 ;A0 scans the message.
bset #0,testdol ;Suppress $ test?
beq.s pstrs ;Yes (used by BDOS/BIOS character output)
cmpi.b #'$',(a0) ;Null string?
beq pstrx ;Yes - do nothing.
pstrs move.l strptr,a1 ;A1 loads the output buffer.
move.l #strbufn,d3
sub.l a1,d3 ;Number of bytes left in buffer
ifne h19
moveq #0,d0
move.w esclen,d0 ;Is a partial escape sequence saved?
beq.s pstrl ;No.
lea escbuf,a2
adda.l d0,a2 ;Continue loading it here.
clr.w esclen ;Reset "saved length" counter.
cmpi.w #2,d0 ;Did we just save one byte?
blt.s pstresc ;Yes - get the remainder.
bhi pstreY2 ;Get the last cursor positioning byte.
subq.l #1,a2 ;Back over dummy byte.
bra pstreY1 ;Get both cursor positioning bytes.
endc
pstrl: cmpi.b #lf,(a0) ;Line feed?
bne.s notlf ;No.
lea escbuf,a2 ;Translate it to a cursor-down sequence.
move.b #$9B,(a2)+
move.b #'B',(a2)+
addq.l #1,a0
bra pstrsub
notlf:
ifne h19
* Optional H19 escape sequence translation
cmpi.b #esc,(a0) ;Escape character?
bne pstrm ;No - treat it normally.
lea escbuf,a2 ;Build translated escape sequence here.
move.b #$9B,(a2)+ ;Start with an AmigaDOS escape character.
addq.l #1,a0 ;Check the next character.
cmpi.b #'$',(a0) ;End of string?
bne.s pstresc ;No - analyze the sequence.
move.w #1,esclen ;We've saved one byte for next time.
bra pstrw ;Write everything up to the ESC character.
pstresc move.b (a0)+,d0
cmpi.b #'[',d0 ;ANSI escape sequence?
beq pstrsub ;Yes - pass the sequence with $9B header.
cmpi.b #'Y',d0
beq.s pstreY ;Set cursor position.
cmpi.b #'@',d0
beq.s pstrein ;Set insert mode.
cmpi.b #'A',d0
blt.s pstreun ;Unknown code - copy it as is.
cmpi.b #'O',d0
beq.s pstreO ;Reset insert mode.
bhi.s pstreun ;Unknown code
move.l a0,-(sp)
lea esctran,a0 ;Translation table with offset
move.b -'A'(a0,d0.w),d2;Get the translated code.
move.l (sp)+,a0
btst #6,d2 ;Does the translated code stand alone?
bne.s pstresb ;No.
subq.l #1,a2 ;Back over stored CSI character.
pstresb move.b d2,(a2)+ ;Get the translated code.
bra.s pstrsub
pstrein move.b #1,insflag ;Set insert mode.
bra.s pstrsbx
pstreO clr.b insflag ;Reset insert mode.
bra.s pstrsbx
pstreY cmpi.b #'Y',d0 ;Set cursor position
bne.s pstreun
cmpi.b #'$',(a0) ;End of string?
bne.s pstreY1 ;No.
move.w #2,esclen ;Indicate we need both position bytes.
bra pstrw ;Finish the sequence next time.
pstreY1 moveq #0,d0
move.b (a0)+,d0 ;Get the first position byte.
bsr pstrcvd ;Convert to decimal in save area.
move.b #';',(a2)+ ;Add the separator character.
cmpi.b #'$',(a0) ;End of string?
bne.s pstreY2 ;No.
sub.l #escbuf,a2 ;Number of bytes saved
move.w a2,esclen
bra pstrw ;Get the last byte next time.
pstreY2 moveq #0,d0
move.b (a0)+,d0 ;Get the last position byte.
bsr pstrcvd ;Convert to decimal in save area.
move.b #'H',(a2)+ ;Terminate the sequence.
bra.s pstrsub
pstreun move.b #esc,escbuf ;Unidentified escape sequence -
move.b d0,(a2)+ ; pass it through as is.
* The translated escape sequence is now in "escbuf" -
* copy it to the output buffer.
pstrsub move.l a2,d0
lea escbuf,a2 ;A2 scans translated escape sequence.
sub.l a2,d0 ;Length of translated escape sequence
subq.l #1,d0
pstrsbl move.b (a2)+,(a1)+ ;Copy substitution to output string.
subq.w #1,d3 ;Count down remaining length.
dbra d0,pstrsbl
pstrsbx cmpi.b #'$',(a0) ;End of string?
beq pstrw ;Yes - write it out.
tst.w d3 ;Is the buffer full?
bmi pstrw ;Yes - write out what we have.
cmpi.b #lf,-1(a0) ;Line feed?
bne pstrl ;No.
tst.b bufflag ;Is console buffering in effect?
beq pstrl ;No.
move.l a1,strptr
bsr dmpstr ;Dump the buffer.
move.l strptr,a1
bra pstrl ;Check for another escape sequence.
* Subroutine to convert the byte in D0 to a character string at (A2)+
pstrcvd subi.b #' '-1,d0 ;Convert to binary row or column number.
divu #10,d0 ;Convert to tens and units.
tst.w d0 ;Is the number 10 or greater?
beq.s pstrcv1 ;No - just create a one-digit number.
addi.b #'0',d0 ;Convert the tens digit to ASCII.
move.b d0,(a2)+ ;Move it to the result field.
pstrcv1 swap d0 ;Get the units digit.
addi.b #'0',d0 ;Convert it to ASCII.
move.b d0,(a2)+
rts
endc
* Normal character processing
pstrm tst.b insflag ;Are we in insert mode?
beq.s pstrmv ;No.
lea escbuf,a2
move.b #$9B,(a2)+ ;Build an insert-character sequence.
move.b #'@',(a2)+
move.b (a0)+,(a2)+ ;Here's the character to insert.
bra.s pstrsub ;Use the substitution routine.
pstrmv move.b (a0)+,(a1)+ ;Move one character.
tst.b bufflag ;Is console buffering in effect?
beq.s pstreos ;No.
cmpi.b #cr,-1(a0) ;Carriage return?
beq.s pstrseg ;Yes - dump the current segment.
cmpi.b #bel,-1(a0) ;Bell?
bne.s pstreos ;No - continue buffering.
pstrseg move.l a1,strptr
bsr dmpstr ;Dump the buffer.
move.l strptr,a1
pstreos cmpi.b #'$',(a0) ;Test for end of string.
dbeq d3,pstrl ;Loop until we get there or buffer is full.
pstrw move.l a1,strptr
tst d3 ;Is the buffer full?
bmi.s pstrdmp ;Yes - dump it regardless.
tst.b bufflag ;Is console buffering in effect?
bne.s pstrnxt ;Yes - don't write anything yet.
pstrdmp bsr dmpstr ;Dump the buffer.
move.l strptr,a1
pstrnxt tst d3 ;Did the output buffer overflow?
bmi pstrs ;Yes - get another section of the message.
pstrx movem.l (sp)+,d2-d3/a1-a2 ;Restore registers
rts
*
* Write the contents of "strbuf" to RAW: if possible, or stdout if not.
* The number of bytes to be written is calculated from "strptr".
*
dmpstr movem.l d2-d3/a0-a1/a6,-(sp)
move.l strptr,d3
move.l #strbuf,d2 ;Address of buffer
move.l d2,strptr ;Reset the buffer pointer.
sub.l d2,d3 ;Length of output string
beq.s dmpstrx ;Zero - don't write anything.
move.l rawhand,d1 ;Assume we're writing to RAW:
bne.s dmpstrp
move.l stdout,d1 ;We don't have RAW: - use stdout.
dmpstrp move.l dosbase,a6
sys Write ;Display the line.
dmpstrx movem.l (sp)+,d2-d3/a0-a1/a6
rts
*
* Convert the file name in the FCB pointed to by A0
* to an AmigaDOS-format file name in the field pointed to by A1.
* D0 is the only other register used by this routine.
*
convfn move.l a1,-(sp)
move.l a0,-(sp) ;Save start address of FCB.
tst.b (a0)+ ;Skip over drive code for now.
moveq #7,d0 ;Maximum of 8 characters for file name
convfn1 cmpi.b #' ',(a0) ;End of file name?
beq.s convfnz ;Yes
move.b (a0)+,(a1)+ ;Move one character of file name.
dbra d0,convfn1 ;Try for more.
convfnz movea.l (sp)+,a0 ;Back to start of FCB.
adda.l #9,a0 ;Go to start of file name extension.
cmpi.b #' ',(a0) ;Do we have an extension?
beq.s convfnx ;No.
move.b #'.',(a1)+ ;Insert extension separator.
moveq #2,d0 ;Maximum of 3 characters for extension.
convfn2 cmpi.b #' ',(a0) ;End of extension?
beq.s convfnx ;Yes.
move.b (a0)+,(a1)+ ;Move one character of extension.
dbra d0,convfn2 ;Try for more.
convfnx clr.b (a1) ;Terminate file name string.
move.l (sp)+,a1
rts
*
* Get the file handle indicated by the number inserted into the
* CP/M FCB by the open routine. It is copied from the file handle
* table entry (whose address is set up as 0(A1,D0.W)) to D1.
* The Z flag will be set if the handle is zero (i.e. file not open).
* A0 points to the FCB.
*
gethand add.l targbase,d1 ;The FCB is here.
movea.l d1,a0
lea handles,a1
moveq #0,d0
move.b 13(a0),d0 ;Get handle number from FCB.
asl.w #2,d0 ;Convert to table offset.
move.l 0(a1,d0.w),d1 ;Get the file handle.
rts
page
*************************************************************************
* *
* Miscellaneous service routines *
* (Inelegant, but rarely used so they stand as is.) *
* *
*************************************************************************
*
* Display the contents of D1 in hex.
*
pbyte move.l #$20018,d0 ;2 nybbles, 24-bit shift first
bra.s phex
pword move.l #$40010,d0 ;4 nybbles, 16-bit shift first
bra.s phex
paddr move.l #$60008,d0 ;6 nybbles, 8-bit shift first
bra.s phex
plong move.l #$80000,d0 ;8 nybbles, no shift first
phex lea workbuf,a0
move.l a0,-(sp)
bsr pdigits
move.b #'$',(a0)+
move.l (sp)+,d1
bsr pstring
rts
*
* Convert the contents of D1 to hex at (A0).
* On exit, A0 points to the next available byte.
*
ubyte move.l #$20018,d0 ;2 nybbles, 24-bit shift first
bra.s pdigits
uword move.l #$40010,d0 ;4 nybbles, 16-bit shift first
bra.s pdigits
uaddr move.l #$60008,d0 ;6 nybbles, 8-bit shift first
bra.s pdigits
ulong move.l #$80000,d0 ;8 nybbles, no shift first
pdigits rol.l d0,d1 ;Do shift.
bra.s pdigent
pdiglop swap d0 ;Save nybble count.
rol.l #4,d1 ;Print variable in d1.
move.l d1,-(sp)
and #$F,d1 ;Isolate the current nybble.
cmp #$A,d1
blt.s ntoa2
add.b #'A'-'9'-1,d1 ;Adjust for digits A through F.
ntoa2 add.b #'0',d1 ;Convert to ASCII.
move.b d1,(a0)+ ;Add to the result string.
move.l (sp)+,d1
pdigent swap d0 ;Get nybble count.
dbra d0,pdiglop
rts
pchar move.b d1,workbuf ;Print the character in D1.
move.b #'$',workbuf+1
move.l #workbuf,d1
bsr pstring
rts
pspace move.l #spacemsg,d1 ;Print a space.
bsr pstring
rts
pcrlf move.l #crlfmsg,d1 ;Print a carriage return and line feed.
bsr pstring
rts
*
* Convert the hex string pointed to by A0 to long in d1.
* Stops on the first invalid hex digit, which is returned in d0.
* A0 is left pointing to this first invalid digit.
* d2 = 1 if any valid digits were found, 0 otherwise.
*
atol moveq #0,d1
moveq #0,d2
atol1 move.b (a0)+,d0 ;Get the current byte.
cmpi.b #$40,d0
blt.s atol2
and #$5F,d0 ;Mask to upper case.
atol2 cmpi.b #'0',d0 ;Check range (0..9,A..F).
blt.s atolend
cmpi.b #'F',d0
bhi.s atolend
cmpi.b #'9',d0
ble.s atol3
cmpi.b #'A'-1,d0
bhi.s atol3
bra.s atolend
atol3 moveq #1,d2 ;Valid characters entered, set flag.
sub.b #'0',d0 ;Convert to binary
cmp.b #$9,d0 ;Digit in range 0..9?
ble.s atol4 ;Yes - conversion is complete
sub.b #'A'-'9'-1,d0 ;Adjust digits A..F.
atol4 ext d0 ;Convert to long.
ext.l d0
asl.l #4,d1 ;Tack it onto d1.
add.l d0,d1
bra.s atol1 ;Try for another digit.
atolend subq.l #1,a0 ;Back onto the first invalid digit.
rts
page
*************************************************************************
* *
* This table contains the mnemonic strings for the 8080 *
* opcodes. These are used in tracing. The first character *
* flags operands. Blank is nothing, A is an address (i.e. *
* a 16-bit value), and C is a constant (i.e. an 8-bit value). *
* *
*************************************************************************
data data
mnops:
dc.b ' NOP$ ALXI B,$ STAX B$ INX B$ ' ;00-03
dc.b ' INR B$ DCR B$ CMVI B,$ RLC$ ' ;04-07
dc.b ' ILLEGAL$ DAD B$ LDAX B$ DCX B$ ' ;08-0B
dc.b ' INR C$ DCR C$ CMVI C,$ RRC$ ' ;0C-0F
dc.b ' ILLEGAL$ALXI D,$ STAX D$ INX D$ ' ;10-13
dc.b ' INR D$ DCR D$ CMVI D,$ RAL$ ' ;14-17
dc.b ' ILLEGAL$ DAD D$ LDAX D$ DCX D$ ' ;18-1B
dc.b ' INR E$ DCR E$ CMVI E,$ RAR$ ' ;1C-1F
dc.b ' ILLEGAL$ALXI H,$ ASHLD $ INX H$ ' ;20-23
dc.b ' INR H$ DCR H$ CMVI H,$ DAA$ ' ;24-27
dc.b ' ILLEGAL$ DAD H$ ALHLD $ DCX H$ ' ;28-2B
dc.b ' INR L$ DCR L$ CMVI L,$ CMA$ ' ;2C-2F
dc.b ' ILLEGAL$ALXI SP,$ASTA $ INX SP$ ' ;30-33
dc.b ' INR M$ DCR M$ CMVI M,$ STC$ ' ;34-37
dc.b ' ILLEGAL$ DAD SP$ ALDA $ DCX SP$ ' ;38-3B
dc.b ' INR A$ DCR A$ CMVI A,$ CMC$ ' ;3C-3F
dc.b ' MOV B,B$ MOV B,C$ MOV B,D$ MOV B,E$' ;40-43
dc.b ' MOV B,H$ MOV B,L$ MOV B,M$ MOV B,A$' ;44-47
dc.b ' MOV C,B$ MOV C,C$ MOV C,D$ MOV C,E$' ;48-4B
dc.b ' MOV C,H$ MOV C,L$ MOV C,M$ MOV C,A$' ;4C-4F
dc.b ' MOV D,B$ MOV D,C$ MOV D,D$ MOV D,E$' ;50-53
dc.b ' MOV D,H$ MOV D,L$ MOV D,M$ MOV D,A$' ;54-57
dc.b ' MOV E,B$ MOV E,C$ MOV E,D$ MOV E,E$' ;58-5B
dc.b ' MOV E,H$ MOV E,L$ MOV E,M$ MOV E,A$' ;5C-5F
dc.b ' MOV H,B$ MOV H,C$ MOV H,D$ MOV H,E$' ;60-63
dc.b ' MOV H,H$ MOV H,L$ MOV H,M$ MOV H,A$' ;64-67
dc.b ' MOV L,B$ MOV L,C$ MOV L,D$ MOV L,E$' ;68-6B
dc.b ' MOV L,H$ MOV L,L$ MOV L,M$ MOV L,A$' ;6C-6F
dc.b ' MOV M,B$ MOV M,C$ MOV M,D$ MOV M,E$' ;70-73
dc.b ' MOV M,H$ MOV M,L$ HLT$ MOV M,A$' ;74-77
dc.b ' MOV A,B$ MOV A,C$ MOV A,D$ MOV A,E$' ;78-7B
dc.b ' MOV A,H$ MOV A,L$ MOV A,M$ MOV A,A$' ;7C-7F
dc.b ' ADD B$ ADD C$ ADD D$ ADD E$ ' ;80-83
dc.b ' ADD H$ ADD L$ ADD M$ ADD A$ ' ;84-87
dc.b ' ADC B$ ADC C$ ADC D$ ADC E$ ' ;88-8B
dc.b ' ADC H$ ADC L$ ADC M$ ADC A$ ' ;8C-8F
dc.b ' SUB B$ SUB C$ SUB D$ SUB E$ ' ;90-93
dc.b ' SUB H$ SUB L$ SUB M$ SUB A$ ' ;94-97
dc.b ' SBB B$ SBB C$ SBB D$ SBB E$ ' ;98-9B
dc.b ' SBB H$ SBB L$ SBB M$ SBB A$ ' ;9C-9F
dc.b ' ANA B$ ANA C$ ANA D$ ANA E$ ' ;A0-A3
dc.b ' ANA H$ ANA L$ ANA M$ ANA A$ ' ;A4-A7
dc.b ' XRA B$ XRA C$ XRA D$ XRA E$ ' ;A8-AB
dc.b ' XRA H$ XRA L$ XRA M$ XRA A$ ' ;AC-AF
dc.b ' ORA B$ ORA C$ ORA D$ ORA E$ ' ;B0-B3
dc.b ' ORA H$ ORA L$ ORA M$ ORA A$ ' ;B4-B7
dc.b ' CMP B$ CMP C$ CMP D$ CMP E$ ' ;B8-BB
dc.b ' CMP H$ CMP L$ CMP M$ CMP A$ ' ;BC-BF
dc.b ' RNZ$ POP B$ AJNZ $ AJMP $ ' ;C0-C3
dc.b 'ACNZ $ PUSH B$ CADI $ RST 0$ ' ;C4-C7
dc.b ' RZ$ RET$ AJZ $ ILLEGAL$' ;C8-CB
dc.b 'ACZ $ ACALL $ CACI $ RST 1$ ' ;CC-CF
dc.b ' RNC$ POP D$ AJNC $ COUT $ ' ;D0-D3
dc.b 'ACNC $ PUSH D$ CSUI $ RST 2$ ' ;D4-D7
dc.b ' RC$ ILLEGAL$AJC $ CIN $ ' ;D8-DB
dc.b 'ACC $ ILLEGAL$CSBI $ RST 3$ ' ;DC-DF
dc.b ' RPO$ POP H$ AJPO $ XTHL$ ' ;E0-E3
dc.b 'ACPO $ PUSH H$ CANI $ RST 4$ ' ;E4-E7
dc.b ' RPE$ PCHL$ AJPE $ XCHG$ ' ;E8-EB
dc.b 'ACPE $ ILLEGAL$CXRI $ RST 5$ ' ;EC-EF
dc.b ' RP$ POP PSW$AJP $ DI$ ' ;F0-F3
dc.b 'ACP $ PUSH P$ CORI $ RST 6$ ' ;F4-F7
dc.b ' RM$ SPHL$ AJM $ EI$ ' ;F8-FB
dc.b 'ACM $ ILLEGAL$CCPI $ RST 7$ ' ;FC-FF
page
*************************************************************************
* *
* Fake FDOS *
* *
*************************************************************************
*
* Fake BDOS for target system
*
fdos dc.b $76,0,$C9 ;BIOS jump table
dc.b $C3,$33,$FF ;Warm boot
dc.b $C3,$36,$FF ;Console status
dc.b $C3,$39,$FF ;Console input
dc.b $C3,$3C,$FF ;Console output
dc.b $C3,$3F,$FF ;List output
dc.b $C3,$42,$FF ;Punch output
dc.b $C3,$45,$FF ;Reader input
dc.b $C3,$48,$FF ;Home disk
dc.b $C3,$4B,$FF ;Select disk
dc.b $C3,$4E,$FF ;Set track
dc.b $C3,$51,$FF ;Set sector
dc.b $C3,$54,$FF ;Set DMA address
dc.b $C3,$57,$FF ;Read
dc.b $C3,$5A,$FF ;Write
dc.b $C3,$5D,$FF ;Get list device status
dc.b $C3,$60,$FF ;Sector translation
*
* Fake BIOS for target system
*
dc.b $76,1,$C9 ;Warm boot
dc.b $76,2,$C9 ;Console status
dc.b $76,3,$C9 ;Console input
dc.b $76,4,$C9 ;Console output
dc.b $76,5,$C9 ;List output
dc.b $76,6,$C9 ;Punch output
dc.b $76,7,$C9 ;Reader input
dc.b $76,8,$C9 ;Home disk *
dc.b $76,9,$C9 ;Select disk *
dc.b $76,10,$C9 ;Set track *
dc.b $76,11,$C9 ;Set sector *
dc.b $76,12,$C9 ;Set DMA address *
dc.b $76,13,$C9 ;Read *
dc.b $76,14,$C9 ;Write *
dc.b $76,15,$C9 ;Get list device status *
dc.b $76,16,$C9 ;Sector translation *
fdoslen equ *-fdos
*
* BDOS function vector table
*
cnop 0,4
bdostab dc.l bdos00,bdos01,bdos02,bdos03,bdos04,bdos05,bdos06,bdos07
dc.l bdos08,bdos09,bdos10,bdos11,bdos12,bdos13,bdos14,bdos15
dc.l bdos16,bdos17,bdos18,bdos19,bdos20,bdos21,bdos22,bdos23
dc.l bdos24,bdos25,bdos26,bdos27,bdos28,bdos29,bdos30,bdos31
dc.l bdos32,bdos33,bdos34,bdos35,bdos36
bdostabn:
*
* BIOS function vector table
*
cnop 0,4
biostab dc.l bdosfn,bios01,bios02,bios03,bios04,bios05,bios06,bios07
dc.l bios08,bios09,bios10,bios11,bios12,bios13,bios14,bios15
biostabn:
page
*************************************************************************
* *
* Messages *
* *
*************************************************************************
dosname dc.b 'dos.library',0
aprompt dc.b 'A>$'
crlfmsg dc.b cr,lf,'$'
spacemsg dc.b ' $'
bsmsg dc.b bs,' ',bs,'$' ;Erases the previous character
simsg dc.b si,'$' ;Resets MSB of each output character
rawspec dc.b 'RAW:0/0/640/200/CP/M Emulator'
dc.b ' by Jim Cathey and Charlie Gibbs - version '
dc.b vermaj&15+'0','.'
dc.b vermin/16+'0',vermin&15+'0',' ('
dc.b revyear/16+'0',revyear&15+'0','/'
dc.b revmonth/16+'0',revmonth&15+'0','/'
dc.b revday/16+'0',revday&15+'0',')',0
rawerr dc.b 'Unable to open RAW: - code $'
setwin dc.b $9B,'0x',$9B,'8y',$9B,'24t',$9B,'80u',$9B,'H',$9B,'J$'
fullmsg dc.b 'Too many files are open!',cr,lf,'$'
illgmsg dc.b cr,lf,'Illegal instruction $'
ilgmsg2 dc.b ' at $'
ilgmsg3 dc.b '.$'
dumpmsg dc.b cr,lf,'Register contents:$'
dmpmsg2 dc.b cr,lf
dc.b '-AF- -BC- -DE- -HL- -SP- -S0- -S1- -S2- -S3- -PC- -op-'
dc.b cr,lf,'$'
dmpmsg3 dc.b 'Q to quit program, G to go on without tracing,'
dc.b 'any other key to continue: $'
ilgbios dc.b cr,lf,'Illegal BIOS call $'
ilgbdos dc.b cr,lf,'Illegal BDOS call $'
tracemsg dc.b cr,lf,'Start trace at >$'
tracemg2 dc.b ' End trace at >$'
btrcmsg dc.b 'Trace BIOS/BDOS calls? >$'
biosmsg dc.b 'BIOS call $'
bdosmsg dc.b 'BDOS call $'
atmsg dc.b ' at $'
esctran dc.b 'ABCD',ff,so,si,'H',$8D,'JKLMP' ;Escape sequence translation
prtname dc.b 'PRT:RAW',0
badprt dc.b 'Unable to open the list device!$'
page
*************************************************************************
* *
* Variable storage *
* *
*************************************************************************
bss bss
savesp ds.l 1 ;Stack pointer save area
dosbase ds.l 1 ;Pointer to dos.library
stdin ds.l 1 ;Keyboard handle (stdin)
stdout ds.l 1 ;Screen handle (stdout)
rawhand ds.l 1 ;RAW: file handle
prthand ds.l 1 ;PRT:RAW file handle
handles ds.l 8 ;File handles for opened files (or zero)
handlen: ;End of file handle table
dmaaddr ds.l 1 ;Current DMA address
comend ds.l 1 ;End of .COM file name on command line
cmdline ds.b 128 ;Command line
cmdlinen: ;End of command line
comname ds.b 13 ;Name of file to load
comnamen: ;End of file name
opnname ds.b 17 ;File name for OPEN or RENAME
renname ds.b 17 ;New file name for RENAME
newrega ds.b 1 ;BIOS/BDOS accumulator work area
workbuf ds.b 80 ;Work buffer for "pstring" (including $)
workbufn: ;End of work buffer
strbuf ds.b 2048 ;String output buffer
strbufn ds.b 8 ;"strbuf" overflow area - must follow "strbuf"!
strptr ds.l 1 ;Current position in "strbuf"
escbuf ds.b 8 ;Translated escape sequence
esclen ds.w 1 ;Number of bytes saved in "escbuf"
cmdflag ds.b 1 ;Take program name from command line.
quitflg ds.b 1 ;"quitprg" exit flag
testdol ds.b 1 ;"pstring" should test for leading $
insflag ds.b 1 ;We're in insert mode.
dumpcnt ds.b 1 ;"dump" counter for pausing
btrcflg ds.b 1 ;Trace BIOS/BDOS calls.
bufflag ds.b 1 ;Console output is buffered.
fcbptr ds.l 1 ;Pointer to current FCB
listopn ds.b 1 ;The list device is open.
*************************************************************************
* *
* Target processor's address space *
* *
*************************************************************************
even
registers ds.b 10 ;Actual storage for 8080's other registers
target ds.b $10000 ;8080's universe
end